物件內的存取器是由get
及set
去設定的,而存取器的設定可以用像是特性一樣的方式去使用他,他們兩者不同的地方是存取器屬性可以以get
和set
去控制該特性被讀寫的功能,get
就代表讀取,set
則是寫入,擁有兩個屬性就可以同時被讀寫。
首先用get
來控制一個存取器的讀取功能,以下實作:
//用get在物件obj內設定一個只能讀取的存取器name
var objA = {
get name(){
return 'objName';
},
};
//讀取name會得到return的'objName'
objA.name; //回傳'objName'
//而雖然他能夠像特性般擁有值,但是實際上該物件是沒有這個特性的
objA; //回傳空物件{}
//因為只有get的讀取屬性,沒有set的寫入,所以他無法設定值
objA.name = 'objA'; //將obj.name的值設定為'objA'
//所以在設定完後檢查該物件,一樣會是空的
objA; //回傳空物件{}
接著我們再來只用set
來控制一個存取器的寫入功能,set
和get
設置的時候有個不同點,set
必須擁有一個能夠傳進引數的變數,因為當我們在寫入值的時候,存取器會將我們設置的值放進該變數中,以下實作:
//用set在物件內設定一個只能寫入的存取器name,括號內的val就是設置的值傳入的位置,這裡我們讓存取器去寫入值到this.objName中,this指的是該物件,所以也就是為objB增加一個特性,讓我們設定的值指定objB.objName
var objB = {
set name(val){
this.objName = val;
},
};
//為該存取器設置值
objB.name = 'objB'; //此時存取器中跑的程式為:objB.objName='objB'
//而我們試著去讀取存取器為我們新增的特性
objB.objName; //會回傳'objB'
//但是因為沒有設置get所以他無法讀出該存取器擁有的值
objB.name; //回傳undefined
//當然該物件會出現存取器為我們設定的特性
objB; //回傳{objName: "objB"}
最後來同時使用get
和set
讓該存取器同時擁有讀取及寫入的功能
//在物件內同時設定擁有讀取和寫入的存取器name,這次我們在get內讀取物件中的objName的值,並將他回傳
var objC = {
get name(){
return this.objName;
},
set name(val){
this.objName = val;
},
};
//讀取該存取器會得到undefined,因為我們還沒有為該特性objName指定值
objC.name; //回傳'undefined'
//接著為該存取器設值'objC'
objC.name = 'objC'; //此時存取器會將'objC'指定給objC.objName
//再試著使用存取器讀出this.objName,也就是objC.objName試試
objC.name; //會回傳'objC'
//最後再來看一下該物件目前的樣子
objC; //會出現一個被存取器設置的特性{objName: "objC"}
基本用法大概就是這樣,但是他和一般特性一樣,如果未用set
設值前get
是指會回傳undefined的,不過既然他的get
中可以寫程式,那就可以想辦法克服這一點,例如:
//在get中加入判斷式,如果再讀取this.objName時,該特性不為undefuned的話就回傳該特性的值,但如果為undefined就回傳預設的'defaultName'
var objD = {
get name(){
if(this.objName){
return this.objName
}
else{
return 'defaultName';
}
},
set name(val){
this.objName = val;
},
};
//在不先設值的情況下去讀取存取器name,因為目前this.objName還是undefined,所以會回傳預設的'defaultName'
objD.name; //回傳'defaultName'
//指定一個值給存取器name
objD.name = 'objD';
//再讀一次存取器name,因為這時候this.objName已經有被指定值,所以就會回傳特性本身的值'objD'
objD.name; //會回傳'objD'
最後要注意的事情是,存取器的名稱不能和特性的名稱重複,否則設置時會發生錯誤,例如:
//如果我們在get和set中都用和存取器本身重複的名稱,那不論讀取或寫入都會出錯
var objE = {
get name(){
return this.name;
},
set name(val){
this.name = val;
},
};
//讀取該存取器的值
objE.name; //會出錯'RangeError'!!!
//設置該存取器的值
objE.name = 'objE'; //還是會出錯'RangeError'!!
以上對於存取器的說明,如果我有觀念錯誤或解釋不清楚的地方,還麻煩各位大大指點了,謝謝大家!
很像 C# 的屬性,這好像是 ES6 的東西,
看了一下瀏覽器支援度,IE9 以上的瀏覽器都支援,
可以考慮用在專案上,哈哈。
對啊!我和我朋友分享的時候他也說很像
是ES6嗎!!!我一直以為是ES5的
我的資訊錯誤,getter setter 是 ES5 的
不好意思,請問一下存取器一般是常用在何種情境上?
似乎除了隱密性以外,有什麼比較需要選擇這種寫法的情況嗎?
謝謝
對不起!!!!我沒有留意到這個留言!!!!
等我下班在回覆您!!!!真的不好意思!!!
哈哈~沒關係!!
感謝大大~
其實我自己都忘記這篇留言了XDD
我突然需要這個回頭看自己文章才發現XD
我昨天剛北漂回來,哈哈!
存取器對物件來說是個很方便的東西,其實他就很像C#中的getter
和setter
能做到的事情就像像大大提到的對不直接操作屬性,讓物件具有隱密性之外,
也可以把console.log
放在get或set中方便做測試看值,
而且如果一開始沒有物件設定該屬性的時候,也能夠利用get來讓屬性直接擁有預設值,
以及因為JavaScript是動態型別,當然物件裡面的屬性也是,所以當我們在設值的時候能夠再set中做簡單的判斷,讓該屬性的類型不會輕易發生改變!
喔喔~!!
感謝大大回覆!!